﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
//using Microsoft.Practices.Unity;
using Ymatou.CommonService;
using Ymatou.User.Common.UserEnum;
using Ymatou.User.Common.UserEnum.Auth;
using Ymatou.User.Dto;
using Ymatou.User.Dto.Auth;
using Ymatou.User.Dto.PasswordAction;
using Ymatou.User.Dto.Register;
using Ymatou.User.ServerResponse;
using Ymatou.UserAuth.Agent.Sso;
using Ymatou.UserAuth.Agent.Token;
using Ymatou.UserAuth.Agent.Utility;
using Ymatou.UserAuth.RestfullCliet;
using Ymatou.UserAuth.Utility;

namespace Ymatou.UserAuth.Agent.Login
{
    /// <summary>
    /// 用户登录认证
    /// </summary>
    public class UserLoginAuthAgent : IUserLoginAuthAgent
    {
        /// <summary>
        /// 根据用户手机获取loginId修改次数
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="actionSource"></param>
        /// <returns></returns>
        public long GetModifyLoginIdCountByMobile(string mobile, UserRegSource actionSource = UserRegSource.App)
        {
            return YmtRestWebClient.Instance.Get<ResponseData<long>, BillsLoginIdModifyEventRequestDto>(new BillsLoginIdModifyEventRequestDto
            {
                ActionSource = actionSource,
                LoginId = mobile //这里的LoginId，对应Mobile
            },
            defReturn: ResponseData<long>.CreateFail(-1, lastErrorMessage: "请求认证错误")
            , errorHandle: err => ApplicationLog.Error(string.Format("用户{0}修改密码请求错误{1}", mobile, err))).Result;
        }

        /// <summary>
        ///  根据用户ID获取loginId修改次数
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="actionSource"></param>
        /// <returns></returns>
        public long GetModifyLoginIdCountByUserId(int userId, UserRegSource actionSource = UserRegSource.App)
        {
            return YmtRestWebClient.Instance.Get<ResponseData<long>, BillsLoginIdModifyEventRequestDto>(new BillsLoginIdModifyEventRequestDto
            {
                ActionSource = actionSource,
                UserId = userId
            },
            defReturn: ResponseData<long>.CreateFail(-1, lastErrorMessage: "请求认证错误")
            , errorHandle: err => ApplicationLog.Error(string.Format("用户{0}修改密码请求错误{1}", userId, err))).Result;
        }


        /// <summary>
        /// 用户登出,（输出登出 javascript），在用户登出及session_end 事件中调用
        /// </summary>
        public void LogOut()
        {
            var token = SSOClient.GetUserClientToken();
            if (string.IsNullOrEmpty(token)) return;
            new UserTokenAgent().RemoveToken(token);
            SSOClient.SSOLogOut();
        }

        /// <summary>
        /// 获取用户凭据
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="wirteSession"></param>
        /// <returns></returns>
        public ResponseData<UserBillsResponseDto> GetBuserBills(int userId/*, bool wirteSession = true*/)
        {
            return this.GetUserBills(userId);
            //var user = this.GetUserBills(userId);
            //if (user.Success)
            //{
            //    if (wirteSession == true)
            //        YmatouSession.SetUserAuthSession(user.Result.UserId, user.Result.LoginId, user.Result.LoginMail, user.Result.LoginMobile);
            //}
            //return user;
        }

        /// <summary>
        /// 用户从cookie登录 。通过认证后返回用户Id，否则返回-1
        /// </summary>
        /// <returns></returns>
        public int LoginByCookie(bool redirectLoginPage = false, bool redirectOpenAuth = false)
        {
            const string _cookieKey = "ymt_login";

            //VerifyUserCookieToken(redirectLoginPage, () => { }
            //    , userid =>
            //    {
            //        var userQueryService = DependencyResolver.Current.GetService<Ymatou.Services.IUserQueryService>();
            //        var user = userQueryService.GetUserInfoViewModel2(userid);
            //        YmatouAuthentication.SetUserEntity(new YmatouPrincipal(user));
            //    }, redirectOpenAuth);

            //var userEntity = YmatouAuthentication.GetUserEntity();
            //if (userEntity != null) return userEntity.iUserId;

            var userId = YmatouUserSession.GetValueByCookieValues(_cookieKey, "Id", "-1").ToInt32(-1);
            var userType = YmatouUserSession.GetValueByCookieValues(_cookieKey, "Type", "-1").ToInt32(-1);
            var userTokenString = YmatouUserSession.GetValueByCookieValues(_cookieKey, "Token");
            if (string.IsNullOrEmpty(userTokenString) || userId == -1 || userType == -1)
            {
                return -1;
            }
            if (AuthHelp.DecryptCookieToken(userId.ToString(), userType.ToString(), userTokenString) == false)
            {
                ApplicationLog.Debug("无效的用户token：" + userTokenString + ",UID: " + userId);
                return -1;
            }
            //从cookie登录认证         
            var authResult = YmtRestWebClient.Instance.Get<ResponseData<UserLoginByCookieResponseDto>, UserLoginByCookieRequestDto>(new UserLoginByCookieRequestDto
            {
                UserId = userId,
                UserType = userType,
                Token = userTokenString,
                ClientIp = ClientIpInfo.GetClientIp()
            }
            , defReturn: ResponseData<UserLoginByCookieResponseDto>.CreateFail(new UserLoginByCookieResponseDto { }, lastErrorMessage: "从cookie登陆错误！")
            , errorHandle: err =>
            {
                ApplicationLog.Error("从cookie登陆错误", err);
            });
            ApplicationLog.Debug(string.Format(" 用户 {0} cookie登录 {1}", userId, authResult.Success));
            return authResult.Success && authResult.Result.Code == LoginResponseCode.OK ? userId : -1;
        }
        /// <summary>
        /// 用户登录认证并修改登录token。认证通过后返回用户Id
        /// </summary>
        /// <param name="loginId">洋码头用户ID或者手机或者登录邮箱</param>
        /// <param name="password"></param>
        /// <param name="upToken">登录成功后更新用户登录token；token 返回用户类型</param>
        /// <param name="tokenTimeOut">保存凭据超时时间</param>
        /// <returns></returns>
        public ResponseData<LoginAuthResponseDto2> LoginAuth(string loginId, string password, Func<int, int> upToken, string sourceType, TimeSpan? tokenTimeOut = null)
        {
            AuthAssert.AssertStringNotNull(loginId, "loginId不能为空");
            AuthAssert.AssertStringNotNull(password, "password不能为空");

            var loginResult = LoginAuth(loginId, password, sourceType);
            AsyncUpdateLoginToken(upToken, loginResult);
            if (!loginResult.Success)
                ApplicationLog.Debug(string.Format("{0} 登录认证返回 {1} {2}", loginId, loginResult.Success, loginResult.LastErrorMessage));
            return loginResult;
        }
        /// <summary>
        /// 获取用户凭据
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="loginPassword"></param>
        /// <returns></returns>
        public ResponseData<UserBillsResponseDto> GetUserBills(int userId, string loginPassword = "")
        {
            AuthAssert.Assert(() => userId > 0, "错误的用户ID");
            return YmtRestWebClient.Instance.Get<ResponseData<UserBillsResponseDto>, UserBillsRequestDto>(new UserBillsRequestDto
             {
                 UserId = userId,
                 LoginPassword = AuthHelp.ParametersEncoding(loginPassword)
             }
             , defReturn: ResponseData<UserBillsResponseDto>.CreateFail(new UserBillsResponseDto { }, lastErrorMessage: "获取用户凭据错误！")
             , errorHandle: err =>
             {
                 ApplicationLog.Error("获取用户凭据错误", err);
             });
        }
        /// <summary>
        /// 用户登录认证。认证通过后返回用户Id
        /// </summary>
        /// <param name="loginId">洋码头用户ID或者手机或者登录邮箱</param>
        /// <param name="password"></param> 
        /// <param name="sourceType">登录客户端类型：www.ymatou.com ，app，dms，xxx.admin,ali,weibo</param>
        /// <param name="tokenTimeOut">保存凭据时间</param>
        /// <returns></returns>
        public ResponseData<LoginAuthResponseDto2> LoginAuth(string loginId, string password, string sourceType = "", TimeSpan? tokenTimeOut = null)
        {
            AuthAssert.AssertStringNotNull(loginId, "loginId不能为空");
            AuthAssert.AssertStringNotNull(password, "password不能为空");


            var loginResult = YmtRestWebClient.Instance.Get<ResponseData<LoginAuthResponseDto2>>("/json/reply/LoginAuthRequestDto"
                , new Dictionary<string, string> 
                {
                  {"LoginId",AuthHelp.ParametersEncoding(loginId)},
                  {"Pas",AuthHelp.ParametersEncoding(password)},
                  {"Description","login"},
                  {"ClientIp",ClientIpInfo.GetClientIp()},
                  {"SourceType",string.IsNullOrEmpty(sourceType) ? AuthHelp.GetRequestSourceHost() : sourceType},
                  {"SSOTokenTimeOut", tokenTimeOut.HasValue ? tokenTimeOut.Value.Ticks.ToString() : "-1"}
                }
                , defReturn: ResponseData<LoginAuthResponseDto2>.CreateFail(new LoginAuthResponseDto2 { }, lastErrorMessage: "请求认证错误！")
                , errorHandle: err => ApplicationLog.Error("请求认证错误", err));
            #region
            //var loginResult = YmtRestWebClient.Instance.Get<ResponseData<LoginAuthResponseDto2>, LoginAuthRequestDto>(new LoginAuthRequestDto
            //{
            //    LoginId = loginId,
            //    Pas = password,
            //    Description = "login",
            //    ClientIp = ClientIpInfo.GetClientIp(),
            //    SourceType = string.IsNullOrEmpty(sourceType) ? AuthHelp.GetRequestSourceHost() : sourceType,
            //    SSOTokenTimeOut = tokenTimeOut.HasValue ? tokenTimeOut.Value.Ticks : -1
            //}
            //, defReturn: ResponseData<LoginAuthResponseDto2>.CreateFail(new LoginAuthResponseDto2 { }, lastErrorMessage: "请求认证错误！")
            //, errorHandle: err =>
            //{
            //    ApplicationLog.Error("请求认证错误", err);
            //});
            #endregion
            //登录失败记录日志
            if (!loginResult.Success)
                ApplicationLog.Debug(string.Format("{0} 登录认证返回 {1} {2}", loginId, loginResult.Success, loginResult.LastErrorMessage));

            return loginResult;
        }

        public ResponseData<LoginAuthResponseDto2> SSOLoginAuth(string loginId, string password, string sourceType = "", TimeSpan? tokenTimeOut = null)
        {
            var loginResult = LoginAuth(loginId, password, sourceType, tokenTimeOut);
            if (loginResult.Success)
            {
                SSOClient.SSOLogin(loginResult.Result.UserData.Sign, tokenTimeOut);
                SetUserAuthSession(loginResult.Result.UserData.UserId/*, loginResult.Result.UserData.LoginId, loginResult.Result.UserData.LoginMobile, loginResult.Result.UserData.LoginMail*/, loginResult.Result.UserData.Sign);
            }
            return loginResult;
        }
      
        /// <summary>
        /// 更新用户登录凭据（loginId，登录邮箱，登录手机）
        /// </summary>
        /// <param name="iUserId"></param>
        /// <param name="newKey"></param>
        /// <param name="type"></param>
        public void UpdateLoginBills(int iUserId, string newKey, LoginKeyType type)
        {
            AuthAssert.AssertStringNotNull(newKey, "newKey不能为空");

            var dto = new UpdateLoginAuthKeyRequestDto
            {
                NewLoginKey = newKey,
                UserId = iUserId,
                Type = (int)type
            };
            YmtRestWebClient.Instance.Post<UpdateLoginAuthKeyRequestDto>(dto, err =>
            {
                ApplicationLog.Error("用户修改登录凭据错误", err);
            });
        }
        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="iUserId"></param>
        /// <param name="newPas"></param>
        /// <param name="aType"></param>
        /// <param name="loginMobile"></param>
        /// <param name="oldPas"></param>
        /// <param name="pasType"></param>
        public ResponseData<ResetPasswordReponseCode> ChangPassword(int iUserId, string newPas, string oldPas, PasswordActionType pasType, ActionType aType = ActionType.ByUserId, string loginMobile = null)
        {
            AuthAssert.AssertStringNotNull(newPas, "newPas不能为空");
            AuthAssert.Assert(() => pasType != PasswordActionType.Other, "错误的密码操作类型");
            var dto = new PasswordRequestDto
            {
                UserId = iUserId,
                NewPassword = newPas,
                OldPassword = oldPas,
                PasActionType = pasType,
                AType = aType,
                LoginMobile = loginMobile
            };
            return YmtRestWebClient.Instance.Post<ResponseData<ResetPasswordReponseCode>, PasswordRequestDto>(dto
                                                , defReturn: ResponseData<ResetPasswordReponseCode>.CreateFail(ResetPasswordReponseCode.DtoError, lastErrorMessage: "修改密码错误！")
                                                , errorHandle: err =>
                                                 {
                                                     ApplicationLog.Error(string.Format("用户{0}修改{1}密码错误", iUserId, pasType), err);
                                                 }
                                                 , requestUri: ConfigurationManager.AppSettings["UserServiceHost"]);
        }
        /// <summary>
        /// 修改交易密码
        /// </summary>
        /// <param name="iUserId"></param>
        /// <param name="newTPas"></param>
        /// <param name="oldTPas"></param>
        /// <param name="aType"></param>
        public ResponseData<ResetPasswordReponseCode> ChangTradingPassword(int iUserId, string newTPas, string oldTPas = null, ActionType aType = ActionType.ByUserId)
        {
            return this.ChangPassword(iUserId, newTPas, oldTPas, PasswordActionType.ModifyTradingPassword, aType);
        }
        /// <summary>
        /// 修改登录密码
        /// </summary>
        /// <param name="iUserId"></param>
        /// <param name="newPas"></param>
        /// <param name="oldPas"></param>
        /// <param name="aType"></param>
        /// <returns></returns>
        public ResponseData<ResetPasswordReponseCode> ChangLoginPassword(int iUserId, string newLPas, string oldLPas = null, ActionType aType = ActionType.ByUserId)
        {
            return this.ChangPassword(iUserId, newLPas, oldLPas, PasswordActionType.ModifyLoginPassword, aType);
        }

        /// <summary>
        /// 根据登录手机修改密码
        /// </summary>
        /// <param name="loginMobile">作为登录凭证的手机号</param>
        /// <param name="newPas"></param>
        public ResponseData<ResetPasswordReponseCode> ChangLoginPasswordByMobile(string loginMobile, string newPas)
        {
            AuthAssert.AssertStringNotNull(newPas, "newPas不能为空");
            AuthAssert.AssertStringNotNull(loginMobile, "loginMobile不能为空");

            return this.ChangPassword(0, newPas, null, PasswordActionType.ModifyLoginPassword, ActionType.ByMobile, loginMobile);

        }
        /// <summary>
        /// 修改登录token
        /// </summary>
        /// <param name="iUserId"></param>
        /// <param name="userType"></param>
        /// <param name="loginTime"></param>
        public void UpdateUserLoginToken(int iUserId, int userType, string loginTime)
        {
            YmtRestWebClient.Instance.Post<UserLoginTokenRequestDto>(new UserLoginTokenRequestDto
            {
                UserId = iUserId,
                UserType = userType,
                LoginTime = loginTime
            }, err =>
            {
                ApplicationLog.Error("(UpdateUserLoginToken)修改用户登录token错误", err);
            });
        }
        /// <summary>
        /// 修改登录token
        /// </summary>
        /// <param name="iUserId"></param>
        /// <param name="userType"></param>
        /// <param name="loginTime"></param>
        public void UpdateUserLoginTokenAsync(int iUserId, int userType, string loginTime)
        {
            YmtRestWebClient.Instance.AsyncPost<UserLoginTokenRequestDto>(new UserLoginTokenRequestDto
            {
                UserId = iUserId,
                UserType = userType,
                LoginTime = loginTime
            }, err =>
            {
                ApplicationLog.Error("(UpdateUserLoginTokenAsync)修改用户登录token错误", err);
            });
        }
        /// <summary>
        /// 获取用户在规定时间内的登录失败次数
        /// </summary>
        /// <param name="loginId"></param>
        /// <param name="timeSpan">分钟：-5 即 5分钟内</param>
        /// <returns></returns>
        public int GetUserLoginFailCount(string loginId, int timeSpan = -5)
        {
            AuthAssert.AssertStringNotNull(loginId, "无效的用户ID");
            return YmtRestWebClient.Instance.Get<int, LoginLimitRequestDto>(
                                            new LoginLimitRequestDto
                                            {
                                                LoginId = AuthHelp.ParametersEncoding(loginId),
                                                TimeSpan = timeSpan
                                            }
                                            , defReturn: 0
                                            , errorHandle: err =>
                                            {
                                                ApplicationLog.Error("GetUserLoginFailCount", err);
                                            });
        }

        public bool MailAuthNotice(int userId)
        {
            AuthAssert.Assert(() => userId > 0, "非法的用户ID");
            return YmtRestWebClient.Instance.Get<ResponseData<LoginBillsResponseDto>, LoginBillsRequestDto>(
                     new LoginBillsRequestDto { UserId = userId, Action = BillsActionType.CheckIsActivateEmail }
                     , defReturn: ResponseData<LoginBillsResponseDto>.CreateFail(new LoginBillsResponseDto { IsNotice = false })
                     , errorHandle: err => { ApplicationLog.Error("获取用户邮箱激活通知错误", err); })
                     .Result.IsNotice;

        }

        public bool UserFirstBindMobile(int userId)
        {
            AuthAssert.Assert(() => userId > 0, "非法的用户ID");
            var result = GetUserBills(userId);
            return result.Success && string.IsNullOrEmpty(result.Result.LoginMobile);
        }

        public bool CheckUserLoginPassword(int userId, string loginPassword)
        {
            AuthAssert.Assert(() => userId > 0, "非法的用户ID");
            AuthAssert.AssertStringNotNull(loginPassword, "密码不能为空");
            return GetUserBills(userId, loginPassword).Success;
        }
        public ResponseData<string> CreateUserBills(int userId, string loginId, string loginPassword, string mail = null, string mobile = null, string tradingPassword = null, bool isYmtLogin = false)
        {
            AuthAssert.AssertStringNotNull(loginId, "用户ID不能为空");
            AuthAssert.AssertStringNotNull(loginPassword, "登录密码不能为空");
            var result = YmtRestWebClient.Instance.Post<ResponseData<string>, UserRegisterRequestDto>(new UserRegisterRequestDto
                                                    {
                                                        UData = new Dictionary<string, object> 
                                                         {
                                                                {"sType","app"}, //业务类别               
                                                                {"sPassword",loginPassword},//              
                                                                {"iUserId",userId},
                                                                {"sLoginId",loginId},
                                                                {"sMobile",mobile},
                                                                {"sTradingPassword",tradingPassword},
                                                                {"sLoginEmail",mail},
                                                                {"bYmtLogin",isYmtLogin}
                                                         }
                                                    }
                                                    , defReturn: ResponseData<string>.CreateFail("create user bills error", lastErrorMessage: "创建凭据错误!")
                                                    , errorHandle: err =>
                                                    {
                                                        ApplicationLog.Error("修改用户登录token错误", err);
                                                    });
            return result;
        }

        public ResponseData<BaseResponse> ChangLoginIdByMobile(string mobile, string newLoginId, UserRegSource actionSoure = UserRegSource.MainSite)
        {
            AuthAssert.AssertStringNotNull(mobile, "手机号不能为空");
            AuthAssert.AssertStringNotNull(newLoginId, "loginId不能为空");

            var result = YmtRestWebClient.Instance.Post<ResponseData<UserLoginBillsVerifyCode>, LoginBillsRequestDto>(
                                                 new LoginBillsRequestDto
                                                 {
                                                     Mobile = mobile,
                                                     LoginId = newLoginId,
                                                     Action = BillsActionType.ModifyLoginId,
                                                     ActionSource = (int)actionSoure
                                                 }
                                                 , defReturn: ResponseData<UserLoginBillsVerifyCode>.CreateFail(UserLoginBillsVerifyCode.SystemError, lastErrorMessage: "调用服务错误")
                                                 , errorHandle: err =>
                                                 {
                                                     ApplicationLog.Error("UserRegisterAgent.ActivateLoginMail", err);
                                                 }, requestUri: UserServiceHost);
            return result.AdapterUserBindBillsResponseMessage("修改成功", "修改失败");
        }
        /// <summary>
        ///  修改登录ID
        /// </summary> 
        public Ymatou.User.ServerResponse.ResponseData<BaseResponse> ModifyUserLoginIdByUserId(int userId, string newLoginId, UserRegSource actionSoure = UserRegSource.MainSite)
        {
            AuthAssert.Assert(() => userId > 0, "非法的用户ID");
            AuthAssert.AssertStringNotNull(newLoginId, "登录ID不能为空");
            var reg = YmtRestWebClient.Instance.Post<Ymatou.User.ServerResponse.ResponseData<UserLoginBillsVerifyCode>, LoginBillsRequestDto>(
                                                   new LoginBillsRequestDto
                                                   {
                                                       UserId = userId,
                                                       LoginId = newLoginId,
                                                       Action = BillsActionType.ModifyLoginId,
                                                       ActionSource = (int)actionSoure
                                                   }
                                                   , defReturn: Ymatou.User.ServerResponse.ResponseData<UserLoginBillsVerifyCode>.CreateFail(UserLoginBillsVerifyCode.SystemError, lastErrorMessage: "修改失败登陆ID错误！")
                                                   , errorHandle: err =>
                                                   {
                                                       ApplicationLog.Error("UserRegisterAgent.ModifyfUserLoginId", err);
                                                   }, requestUri: UserServiceHost);
            return reg.AdapterUserBindBillsResponseMessage("修改成功", "修改失败");
        }
        private void AsyncUpdateLoginToken(Func<int, int> upToken, ResponseData<LoginAuthResponseDto2> loginResult)
        {
            if (loginResult.Success && loginResult.Result.Code == LoginResponseCode.OK)
            {
                var userID = loginResult.Result.UserData.UserId;

                var uType = upToken(Convert.ToInt32(userID));
                YmtRestWebClient.Instance.AsyncPost<UserLoginTokenRequestDto>(new UserLoginTokenRequestDto
                {
                    UserId = Convert.ToInt32(userID),
                    UserType = uType,
                    LoginTime = DateTime.Now.ToString("yyyyMMddHHmmss")
                }, err =>
                {
                    ApplicationLog.Error("修改用户登录token错误", err);
                });
            }
        }
        private static void SetUserAuthSession(int userId, string token)
        {
            var str = string.Format("{0},{1}", userId, token);
            HttpContext.Current.Session["_auth_identity_"] = str;
        }

        /// <summary>
        /// 码头api调用
        /// </summary>
        private string UserServiceHost
        {
            get
            {
                return ConfigurationManager.AppSettings["UserServiceHost"];
            }
        }
    }
}
